/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/
#define SET_SCL HAL_GPIO_WritePin(SCL_GPIO_Port,SCL_Pin,GPIO_PIN_SET)
#define CLR_SCL HAL_GPIO_WritePin(SCL_GPIO_Port,SCL_Pin,GPIO_PIN_RESET)

#define SET_SDA HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_SET)
#define CLR_SDA HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_RESET)

#define READ_SDA HAL_GPIO_ReadPin(SDA_GPIO_Port,SDA_Pin)

/* Private function prototypes------------------------------------------------*/
static void IIC_Init(void);
static void IIC_Start(void);
static void IIC_Stop(void);
static void Write_Byte(uint8_t );
static uint8_t Recive_Byte(void);
static void SendACK(ACK_Value_t );
static ACK_Value_t ReciveACK(void);
static void IIC_Delay_us(uint8_t );
/* Private variables----------------------------------------------------------*/

/* Public variables-----------------------------------------------------------*/
IIC_Soft_t IIC_Soft = 
{
    IIC_Init,
    IIC_Start,
    IIC_Stop,
    Write_Byte,
    Recive_Byte,
    SendACK,
    ReciveACK
};

/*
* @name   IIC_Init
* @brief  IIC初始化
* @param  None
* @retval None
*/
static void IIC_Init()
{
    SET_SCL;
    SET_SDA;
}

/*
* @name   IIC_Start
* @brief  起始信号
* @param  None
* @retval None
*/
static void IIC_Start()
{
    //SCL为高电平时，SDA的下降沿为IIC的起始信号
    SET_SCL;
    SET_SDA;
    IIC_Delay_us(1);
    CLR_SDA;
    IIC_Delay_us(10);
    CLR_SCL;
    IIC_Delay_us(1);
}

/*
* @name   IIC_Stop
* @brief  停止信号
* @param  None
* @retval None
*/
static void IIC_Stop()
{  
    //SCL为高电平时，SDA的上升沿为IIC的停止信号
    CLR_SDA;
    SET_SCL;
    IIC_Delay_us(10);
    SET_SDA;
}

/*
* @name   Write_Byte
* @brief  主机发送一个字节
* @param  WR_Byte：要发送的数据
* @retval None
*/
static void Write_Byte(uint8_t WR_Byte)
{
    uint8_t i;
    //传输一个字节
    /*SCL为低电平时，SDA准备数据,接着SCL为高电平，读取SDA数据
	数据按8位传输，高位在前，利用for循环逐个接收*/
    for(i=0;i<8;i++)
    {
        CLR_SCL;            //拉低SCL
        IIC_Delay_us(1);
        if((WR_Byte&BIT7) == BIT7)
        {
            SET_SDA;        //往SDA上放1
        }
        else
        {
            CLR_SDA;        //往SDA上放0
        }
        IIC_Delay_us(1);
        SET_SCL;            //拉高SCL，从机读取数据
        IIC_Delay_us(10);
        WR_Byte <<= 1;      //左移一位，发送下一位
    }
}

/*
* @name   Recive_Byte
* @brief  主机接收一个字节
* @param  None
* @retval 接收到的数据
*/
static uint8_t Recive_Byte()
{
    uint8_t i,Re_Byte = 0x00;

    //释放SDA，将控制权交给从机，即SDA = 1
    SET_SDA;
    //接收一个字节
    for(i=0;i<8;i++)
    {
        CLR_SCL;    //拉低SCL，从机SDA准备数据
        IIC_Delay_us(10);

        SET_SCL;    //拉高SCL，读取数据
        IIC_Delay_us(10);
        if(READ_SDA == GPIO_PIN_SET)
        {
            Re_Byte|=(BIT7>>i);
        } 
    }
    return Re_Byte;
}

/*
* @name   SendACK
* @brief  主机发送应答
* @param  ACK_Value：ACK：应答，NACK：非应答
* @retval None
*/
static void SendACK(ACK_Value_t ACK_Value)
{
    CLR_SCL;        //拉低SCL，主机准备发送应答信息
    IIC_Delay_us(1);
    //发送应答信息
    if(ACK_Value == ACK)
    {
        CLR_SDA;    //0表示应答       
    }
    else
    {
        SET_SDA;    //1表示非应答
    }
    IIC_Delay_us(1);
    SET_SCL;        //拉高SCL，主机发送应答
    IIC_Delay_us(1);
    //释放SDA数据线
	//SCL先清零，再释放SDA，防止连续传输数据时，从机错将SDA释放信号当成NACk信号
    CLR_SCL;        //拉低SCL
    SET_SDA;        //因为主机发送应答后，从机可能会继续发送数据，所以控制权要给到从机
    IIC_Delay_us(1);
}

/*
* @name   ReciveACK
* @brief  主机接收应答，判断从机是否应答
* @param  None
* @retval 从机的应答
*/
static ACK_Value_t ReciveACK()
{
    uint8_t RecAck;
    CLR_SCL;            //拉低SCL
    SET_SDA;            //主机释放SDA,将控制权交给从机，即SDA = 1
    IIC_Delay_us(1);
    SET_SCL;            //拉高SCL，读取SDA的值
    IIC_Delay_us(10);
    RecAck = READ_SDA;  //读取SDA的值，0表示应答，1表示非应答
    CLR_SCL;
    IIC_Delay_us(1);
    return (ACK_Value_t)RecAck;
}

/*
* @name   IIC_Delay_us
* @brief  IIC延时函数——微秒级，
* @param  us：要延时的时间
* @retval None
*/
static void IIC_Delay_us(uint8_t us)
{
    uint16_t i;
	//通过示波器测量进行校准
    while(us--)
    {
        for(i=0;i<7;i++);
    }
}
/********************************************************
  End Of File
********************************************************/
